#include "include/segment.h"
.text
.code64 // Assembly generates 64 bit machine instructions
.start64:
  
  // [Test] Turn off identity mapping, LV-4 root page table item 0
  //mov $0x30000, %eax
  //movq 0x0, (%rax)

  lgdt gdtr // Notify processor of new segment descriptor table address
  lidt idtr // Load to IDTR register

  mov $KERNEL_DS, %ax // Kernel data segment selector init
  mov %ax, %ds
  mov %ax, %ss
  mov %ax, %es
  mov %ax, %fs
  mov %ax, %gs
  
  // %rsp(stack top pointer) initially points to the bottom of the newly created stack
  mov $task0_stack, %rsp
  
  push $main // push main address to stack, expanding high 32-bit to 1
  ret // pop up to RIP

.align 64
.globl gdt
gdt: // Definition of new segment descriptor table
  .quad 0x0000000000000000 /* (8B) 0 reserved */
  .quad 0x00209a0000000000 /* (8B) 1 kernel cs */
  .quad 0x0000920000000000 /* (8B) 2 kernel ds */
  .quad 0x0000000000000000 /* (8B) 3 user32 cs */
  .quad 0x0000f20000000000 /* (8B) 4 user ds */
  .quad 0x0020fa0000000000 /* (8B) 5 user64 cs */
  .fill 128, 8, 0
gdt_end:

gdtr: // Segment descriptor table address definition, total of 10B [?]
  .word gdt_end - gdt // Low 16 bits - Table length - Starting and ending offset difference of 2B
  .quad gdt // High 32-bit - Table Address 8B

idtr:
  .word 16 * 256 // 2B low, interrupt descriptor table length(256 * 16B)
  .quad idt_table // 8B high, interrupt descriptor table address

// 4KB stack
  .fill 4096, 1, 0
.globl task0_stack
task0_stack:

// Simulate switching back from kernel mode to user mode
.globl ret_from_kernel
ret_from_kernel:
  // Debug test jump in
  // mov $0x3f8, %dx
  // mov $'R', %ax
  // out %ax, %dx
  mov $USER_DS, %rax
  movw %ax, %ds
  movw %ax, %es
  movw %ax, %fs
  movw %ax, %gs
  iretq

.globl idle_task_entry
idle_task_entry: // Idle processes task 0
1:
  sti // Enable processor response interrupt flag
  hlt
  jmp 1b